#' @title GGplot2绘制森林图
#' @description GGplot2绘制森林图
#' @param DF 输入数据dataframe
#' @param Feature_col 特征信息所在列
#' @param Hazard_Ratio_col HR所在列
#' @param lower_95_col 95置信区间下限
#' @param upper_95_col 95置信区间上限
#' @param p_col p值所在列
#' @param rel_widths 特征，HR，p值，点线图所占宽度比例
#' @export
#' @usage pp <- ForestPlot_GG(DF, "sample", "HR", "lower_95", "upper_95", "p")
#' @author *WYK*
#'
ForestPlot_GG <- function(DF, Feature_col = "gene", Hazard_Ratio_col = "",
                          lower_95_col = "", upper_95_col = "", p_col = "",
                          rel_widths = c(.7, 1.1, .5, 2.5), order_by_HR = FALSE) {
    if (isTRUE(order_by_HR)) {
        DF <- DF %>% arrange(get0(Hazard_Ratio_col))
    }

    DF[["Type"]] <- factor(ifelse(DF[[Hazard_Ratio_col]] <= 1, "HR < 1", "HR > 1"))
    DF[[Feature_col]] <- factor(DF[[Feature_col]], levels = DF[[Feature_col]])

    if (any(DF[[lower_95_col]] == 0)) {
        message("上下区间中有0存在，自动填充为1e-5")
        v <- DF[[lower_95_col]][DF[[lower_95_col]] == 0] + 1e-5
        DF[[lower_95_col]][DF[[lower_95_col]] == 0] <- v
    }

    if (any(DF[[upper_95_col]] == 0)) {
        v <- DF[[upper_95_col]][DF[[upper_95_col]] == 0] + 1e-5
        DF[[upper_95_col]][DF[[upper_95_col]] == 0] <- v
    }

    p1 <- ggplot(DF, aes_string(Hazard_Ratio_col, Feature_col, color = "Type")) +
        geom_point(size = 2, shape = 15) +
        geom_errorbarh(aes_string(xmax = upper_95_col, xmin = lower_95_col), height = 0.2) +
        #   scale_x_continuous(limits= c(0, 4), breaks= seq(0, 4, 1))+
        geom_vline(aes(xintercept = 1)) +
        xlab("HR(95%CI)") +
        ylab(" ") +
        theme_minimal(base_size = 12) +
        theme(
            axis.text.y = element_blank(),
            axis.ticks.y = element_blank(),
            axis.text.x = element_text(color = "black"),
            axis.title.y = element_blank(),
            plot.margin = unit(rep(0, 4), "cm"),
            legend.title = element_blank(),
            legend.key = element_blank(), # 图例键为空
            legend.text = element_text(color = "black", size = 9), # 定义图例文本
            legend.spacing.x = unit(0.1, "cm"), # 定义文本书平距离
            legend.spacing.y = unit(0.1, "cm"),
            legend.key.width = unit(0.2, "cm"), # 定义图例水平大小
            legend.key.height = unit(0.2, "cm"), # 定义图例垂直大小
            legend.background = element_blank(), # 设置背景为空
            legend.box.background = element_rect(colour = "black"), # 图例绘制边框
            legend.justification = c(1, 0),
            legend.position = "none",
            axis.line.y.left = element_blank()
        ) +
        scale_color_manual(values = c("HR < 1" = "steelblue", "HR > 1" = "#aa1313")) +
        theme(axis.title.x.bottom = element_blank()) +
        coord_trans(x = "log2")

    # p1 + coord_trans(x="log2")

    p2 <- DF %>%
        mutate(group = "A") %>%
        ggplot(aes_string("group", Feature_col)) +
        geom_text(aes_string("group", Feature_col, label = Feature_col), size = 3, color = "black") +
        GGally::geom_stripped_rows(odd = "#8585851a", even = "#dbdbdb15") +
        theme_minimal(base_size = 12) +
        theme(
            panel.grid.major = element_blank(),
            axis.text = element_blank(),
            axis.ticks = element_blank(),
            axis.title.y = element_blank(),
            plot.margin = unit(rep(0, 4), "cm")
        ) +
        labs(x = Feature_col) +
        scale_x_discrete(position = "top")

    if (!"HR(95%CI)" %in% colnames(DF)) {
        DF[["HR(95%CI)"]] <- str_c(round(DF[[Hazard_Ratio_col]], 2), "(", round(DF[[lower_95_col]], 2), "-", round(DF[[upper_95_col]], 2), ")")
        if (any(duplicated(DF[["HR(95%CI)"]]))) {
            i <- duplicated(DF[["HR(95%CI)"]])
            DF[["HR(95%CI)"]][i] <- paste0(DF[["HR(95%CI)"]][i], " ")
        }
        if (any(duplicated(DF[["HR(95%CI)"]]))) {
            i <- duplicated(DF[["HR(95%CI)"]])
            DF[["HR(95%CI)"]][i] <- paste0(DF[["HR(95%CI)"]][i], " ")
        }
        if (any(duplicated(DF[["HR(95%CI)"]]))) {
            i <- duplicated(DF[["HR(95%CI)"]])
            DF[["HR(95%CI)"]][i] <- paste0(DF[["HR(95%CI)"]][i], " ")
        }
        if (any(duplicated(DF[["HR(95%CI)"]]))) {
            i <- duplicated(DF[["HR(95%CI)"]])
            DF[["HR(95%CI)"]][i] <- paste0(" ", DF[["HR(95%CI)"]][i])
        }

        DF[["HR(95%CI)"]] <- factor(DF[["HR(95%CI)"]], levels = DF[["HR(95%CI)"]])
    } else {
        DF[["HR(95%CI)"]] <- factor(DF[["HR(95%CI)"]], levels = DF[["HR(95%CI)"]])
    }

    p3 <- DF %>%
        mutate(group = "A") %>%
        ggplot(aes(group, forcats::as_factor(`HR(95%CI)`))) +
        geom_text(aes(group, `HR(95%CI)`, label = `HR(95%CI)`),
            size = 3, color = "black",
            position = position_identity()
        ) +
        GGally::geom_stripped_rows(odd = "#8585851a", even = "#dbdbdb1d") +
        theme_minimal(base_size = 12) +
        theme(
            panel.grid.major = element_blank(),
            axis.text = element_blank(),
            axis.ticks = element_blank(),
            axis.title.y = element_blank(),
            plot.margin = unit(rep(0, 4), "cm")
        ) +
        labs(x = "HR(95%CI)") +
        scale_x_discrete(position = "top")

    DF[["P"]] <- as.character(ifelse(DF[[p_col]] < 0.001, "<0.001", sprintf("%.3f", DF[[p_col]])))

    p4 <- DF %>%
        mutate(group = "A") %>%
        ggplot(aes_string("group", Feature_col)) +
        geom_text(aes_string("group", label = "P"), size = 3, color = "black") +
        GGally::geom_stripped_rows(odd = "#8585851a", even = "#dbdbdb15") +
        theme_minimal(base_size = 12) +
        theme(
            panel.grid.major = element_blank(),
            axis.text = element_blank(),
            axis.ticks = element_blank(),
            axis.title.y = element_blank(),
            plot.margin = unit(rep(0, 4), "cm")
        ) +
        labs(x = "P") +
        scale_x_discrete(position = "top")

    p5 <- cowplot::plot_grid(plotlist = list(p2, p3, p4, p1), rel_widths = rel_widths, nrow = 1, align = "vh") +
        theme(plot.margin = unit(c(.1, .1, .1, .1), "cm"))

    return(p5)
}


# 测试部分
if (FALSE) {
    # 随机生成一个数据框
    DF <- tibble(
        sample = sample(letters[1:10]), HR = runif(10, 0, 2), lower_95 = runif(10, 0, 1),
        upper_95 = runif(10, 1, 2), p = runif(10, .001, .05)
    ) %>%
        mutate(HR = ifelse(HR < upper_95,
            {
                a <- HR
                HR <- upper_95 - .1
                upper_95 <- a
            },
            HR
        )) %>%
        mutate(HR = ifelse(HR > lower_95,
            {
                b <- HR
                HR <- lower_95 + .1
                lower_95 <- b
            },
            HR
        ))

    # 函数运行部分
    p <- ForestPlot_GG(DF,
        Feature_col = "sample", Hazard_Ratio_col = "HR",
        lower_95_col = "lower_95", upper_95_col = "upper_95", p_col = "p"
    )

    # ggsave
    ggsave(
        plot = pp,
        filename = "/Pub/Users/wangyk/Project_wangyk/Codelib_YK/some_scr/developing/forest_plot_GGplot2/aa.pdf",
        width = 5, height = 4
    )
}


ForestPlot_GG_v2 <- function(DF, Feature_col = "gene", ratio_col = "",
                             lower_95_col = "", upper_95_col = "", p_col = "",
                             rel_widths = c(.7, 1.1, .5, 2.5), order_by_OR = FALSE, ratio_name = "OR") {
    if (isTRUE(order_by_OR)) {
        DF <- DF %>% arrange(get0(ratio_col))
    }

    DF <- DF %>% mutate(across(.cols = any_of(c(ratio_col, lower_95_col, upper_95_col)), .fns = list(as.numeric)))

    DF[["Type"]] <- factor(ifelse(DF[[ratio_col]] <= 1, str_glue("{ratio_name} < 1"), str_glue("{ratio_name} < 1")))
    # DF[[Feature_col]] <- factor(DF[[Feature_col]], levels = DF[[Feature_col]])

    if (any(DF[[lower_95_col]] == 0)) {
        message("上下区间中有0存在，自动填充为1e-5")
        v <- DF[[lower_95_col]][DF[[lower_95_col]] == 0] + 1e-5
        DF[[lower_95_col]][DF[[lower_95_col]] == 0] <- v
    }

    if (any(DF[[upper_95_col]] == 0)) {
        v <- DF[[upper_95_col]][DF[[upper_95_col]] == 0] + 1e-5
        DF[[upper_95_col]][DF[[upper_95_col]] == 0] <- v
    }

    p1 <- ggplot(DF, aes_string(ratio_col, Feature_col, color = "Type")) +
        geom_point(size = 2, shape = 18) +
        geom_errorbarh(aes_string(xmax = upper_95_col, xmin = lower_95_col), height = 0.2) +
        #   scale_x_continuous(limits= c(0, 4), breaks= seq(0, 4, 1))+
        geom_vline(aes(xintercept = 1)) +
        xlab(str_glue("{ratio_name}(95%CI)")) +
        ylab(" ") +
        theme_minimal(base_size = 12) +
        theme(
            axis.text.y = element_blank(),
            axis.ticks.y = element_blank(),
            axis.text.x = element_text(color = "black"),
            axis.title.y = element_blank(),
            plot.margin = unit(rep(0, 4), "cm"),
            legend.title = element_blank(),
            legend.key = element_blank(), # 图例键为空
            legend.text = element_text(color = "black", size = 9), # 定义图例文本
            legend.spacing.x = unit(0.1, "cm"), # 定义文本书平距离
            legend.spacing.y = unit(0.1, "cm"),
            legend.key.width = unit(0.2, "cm"), # 定义图例水平大小
            legend.key.height = unit(0.2, "cm"), # 定义图例垂直大小
            legend.background = element_blank(), # 设置背景为空
            legend.box.background = element_rect(colour = "black"), # 图例绘制边框
            legend.justification = c(1, 0),
            legend.position = "none",
            axis.line.y.left = element_blank()
        ) +
        scale_color_manual(values = c("OR < 1" = "steelblue", "OR > 1" = "#aa1313")) +
        theme(axis.title.x.bottom = element_blank()) +
        coord_trans(x = "log2")

    # p1 + coord_trans(x="log2")

    p2 <- DF %>%
        mutate(group = "A") %>%
        ggplot(aes_string("group", Feature_col)) +
        geom_text(aes_string("group", Feature_col, label = Feature_col), size = 3, color = "black") +
        GGally::geom_stripped_rows(odd = "#8585851a", even = "#dbdbdb15") +
        theme_minimal(base_size = 12) +
        theme(
            panel.grid.major = element_blank(),
            axis.text = element_blank(),
            axis.ticks = element_blank(),
            axis.title.y = element_blank(),
            plot.margin = unit(rep(0, 4), "cm")
        ) +
        labs(x = Feature_col) +
        scale_x_discrete(position = "top")

    if (!str_glue("{ratio_name}(95%CI)") %in% colnames(DF)) {
        DF[[str_glue("{ratio_name}(95%CI)")]] <- str_c(round(DF[[ratio_col]], 2), "(", round(DF[[lower_95_col]], 2), "-", round(DF[[upper_95_col]], 2), ")")
        if (any(duplicated(DF[[str_glue("{ratio_name}(95%CI)")]]))) {
            counts_1$add()
            if(counts_1$i < 6){
                DF[[str_glue("{ratio_name}(95%CI)")]] <- make_unique(DF[[str_glue("{ratio_name}(95%CI)")]])
            }else {
               DF[[str_glue("{ratio_name}(95%CI)")]] <- make_unique2(DF[[str_glue("{ratio_name}(95%CI)")]])
            }
        }

        DF[[str_glue("{ratio_name}(95%CI)")]] <- factor(DF[[str_glue("{ratio_name}(95%CI)")]])
    } else {
        DF[[str_glue("{ratio_name}(95%CI)")]] <- factor(DF[[str_glue("{ratio_name}(95%CI)")]])
    }

    p3 <- DF %>%
        mutate(group = "A") %>%
        ggplot(aes(x = group, y = `HR(95%CI)`)) +
        geom_text(aes(label = `HR(95%CI)`),
            size = 3, color = "black", position = position_identity()
        ) +
        GGally::geom_stripped_rows(odd = "#8585851a", even = "#dbdbdb1d") +
        theme_minimal(base_size = 12) +
        theme(
            panel.grid.major = element_blank(),
            axis.text = element_blank(),
            axis.ticks = element_blank(),
            axis.title.y = element_blank(),
            plot.margin = unit(rep(0, 4), "cm")
        ) +
        labs(x = str_glue("{ratio_name}(95%CI)")) +
        scale_x_discrete(position = "top")

    DF[["P"]] <- as.character(ifelse(DF[[p_col]] < 0.001, "<0.001", sprintf("%.3f", DF[[p_col]])))

    p4 <- DF %>%
        mutate(group = "A") %>%
        ggplot(aes_string("group", Feature_col)) +
        geom_text(aes_string("group", label = "P"), size = 3, color = "black") +
        GGally::geom_stripped_rows(odd = "#8585851a", even = "#dbdbdb15") +
        theme_minimal(base_size = 12) +
        theme(
            panel.grid.major = element_blank(),
            axis.text = element_blank(),
            axis.ticks = element_blank(),
            axis.title.y = element_blank(),
            plot.margin = unit(rep(0, 4), "cm")
        ) +
        labs(x = "P") +
        scale_x_discrete(position = "top")

    p5 <- cowplot::plot_grid(plotlist = list(p2, p3, p4, p1), rel_widths = rel_widths, nrow = 1, align = "vh") +
        theme(plot.margin = unit(c(.1, .1, .1, .1), "cm"))

    
    return(p5)
}


# 定义递归函数来处理字符串
# 定义一个递归函数
make_unique <- function(strings) {
  # 检查是否存在重复元素
  duplicates <- duplicated(strings)
  
  # 如果没有重复元素，则返回
  if (!any(duplicates)) {
    return(strings)
  }
  
  # 对重复元素加空格
  strings[duplicates] <- paste0(" ", strings[duplicates])
  
  # 递归调用，直到所有元素都是唯一的
  make_unique(strings)
}

make_unique2 <- function(strings) {
  # 检查是否存在重复元素
  duplicates <- duplicated(strings)
  
  # 如果没有重复元素，则返回
  if (!any(duplicates)) {
    return(strings)
  }
  
  # 对重复元素加空格
  strings[duplicates] <- paste0(strings[duplicates]," ")
  
  # 递归调用，直到所有元素都是唯一的
  make_unique(strings)
}



library(R6)
counts <- R6::R6Class("counts", public = list(
    i = NA,
    initialize = \(...){
        self$i <- 1
    },
    add = \(){
        self$i <- self$i + 1
        message(self$i)
    },
    clear = \(){
        self$i <- 1
    },
    print = \(){
        cli::cli_alert("当前计数：{self$i}")
    }
))
counts_1 <- counts$new()

